﻿@{
    ViewBag.Title = "BucketGame2";
    Layout = "~/Views/Shared/_Page.cshtml";
}

<h2>Bucket Game2</h2>

<style>
    output {
        color: blue;
    }

    .floatingControls {
        background: rgba(210, 210, 0, 0.1);
        border: thin solid #d2d200;
        -webkit-box-shadow: rgba(0,0,0,0.3) 2px 2px 4px;
        -moz-box-shadow: rgba(100,140,230,0.5) 2px 2px 6px;
        box-shadow: rgba(100,140,230,0.5) 2px 2px 6px;
        padding: 15px;
        font: 12px Arial;
        color: #000000;
    }

    #canvas {
        background: #68ff68;
        -webkit-box-shadow: 4px 4px 8px rgba(0,0,0,0.5);
        -moz-box-shadow: 4px 4px 8px rgba(0,0,0,0.5);
        box-shadow: 4px 4px 8px rgba(0,0,0,0.5);
        cursor: pointer;
    }

    #scoreboard {
        background: rgba(255,255,255,0.5);
        position: absolute;
        left: 755px;
        top: 200px;
        color: blue;
        font-size: 18px;
        padding: 5px;
    }

    #controls {
        position: absolute;
        left: 285px;
        top: 180px;
    }
</style>

<h2>Bucket Game</h2>

<canvas id='canvas' width='800' height='450'>
    Canvas not supported
</canvas>

<div id='scoreboard' class='floatingControls'>0</div>

<div id='controls' class='floatingControls'>
    Launch velocity  (m/s): <output id='launchVelocityOutput'></output> m/s<br/>
    Launch angle (degrees): <output id='launchAngleOutput'></output> degrees<br/>
</div>

<script src='/JsLib/zeus/animation/zeus.animation.frame.js'></script>
<script src='/JsLib/zeus/game/zeus.sprites.js'></script>
<script type="text/javascript">
    var canvas = document.getElementById('canvas'),
    context = canvas.getContext('2d'),
    scoreboard = document.getElementById('scoreboard'),
    launchVelocityOutput = document.getElementById('launchVelocityOutput'),
    launchAngleOutput = document.getElementById('launchAngleOutput'),

    launchTime = undefined,

    score = 0,
    lastScore = 0,
    lastMouse = { left: 0, top: 0 },

    threePointer = false,
    needInstructions = true,

    // ball type make the point
    ballType = 0;

    LAUNCHPAD_X = 50,
    LAUNCHPAD_Y = context.canvas.height - 50,
    LAUNCHPAD_WIDTH = 50,
    LAUNCHPAD_HEIGHT = 12,
    BALL_RADIUS = 8,
    ARENA_LENGTH_IN_METERS = 10,
    INITIAL_LAUNCH_ANGLE = Math.PI / 4,

    launchAngle = INITIAL_LAUNCH_ANGLE,
    pixelsPerMeter = canvas.width / ARENA_LENGTH_IN_METERS,

    // LaunchPad.................................................

    launchPadPainter = {
        LAUNCHPAD_FILL_STYLE: 'rgb(100,140,230)',

        paint: function (ledge, context) {
            context.save();
            context.fillStyle = this.LAUNCHPAD_FILL_STYLE;
            context.fillRect(LAUNCHPAD_X, LAUNCHPAD_Y,
                             LAUNCHPAD_WIDTH, LAUNCHPAD_HEIGHT);
            context.restore();
        }
    },

    launchPad = new Sprite('launchPad', launchPadPainter),

    // Ball......................................................

    ballPainter = {
        BALL_FILL_STYLE: 'rgb(255,255,0)',
        BALL_STROKE_STYLE: 'rgb(0,0,0,0.4)',

        paint: function (ball, context) {
            context.save();
            context.shadowColor = undefined;
            context.lineWidth = 2;
            context.fillStyle = this.BALL_FILL_STYLE;
            context.strokeStyle = this.BALL_STROKE_STYLE;

            context.beginPath();
            context.arc(ball.left, ball.top,
                        ball.radius, 0, Math.PI * 2, false);

            context.clip();
            context.fill();
            context.stroke();
            context.restore();
        }
    },

    // Lob behavior..............................................

    lob = {
        lastTime: 0,
        GRAVITY_FORCE: 9.81, // m/s/s

        applyGravity: function (elapsed) {
            ball.velocityY = (this.GRAVITY_FORCE * elapsed) -
                             (launchVelocity * Math.sin(launchAngle));
        },

        updateBallPosition: function (updateDelta) {
            ball.left += ball.velocityX * (updateDelta) * pixelsPerMeter;
            ball.top += ball.velocityY * (updateDelta) * pixelsPerMeter;
        },

        checkForThreePointer: function () {
            if (ball.top < 0) {
                threePointer = true;
            }
        },

        checkBallBounds: function () {
            if (ball.top > canvas.height || ball.left > canvas.width) {
                reset();
            }
        },

        execute: function (ball, context, time) {
            var updateDelta,
                elapsedFlightTime;

            if (ballInFlight) {
                if (launchTime === undefined) launchTime = time;
                elapsedFrameTime = (time - this.lastTime) / 1000,
                elapsedFlightTime = (time - launchTime) / 1000;

                this.applyGravity(elapsedFlightTime);
                this.updateBallPosition(elapsedFrameTime);
                this.checkForThreePointer();
                this.checkBallBounds();
            }
            this.lastTime = time;
        }
    },

    ball = new Sprite('ball', ballPainter, [lob]),
    ballInFlight = false,

    // Bucket....................................................

    catchBall = {
        ballInBucket: function () {
            /*
            return ball.left > bucket.left + bucket.width / 2 &&
                   ball.left < bucket.left + bucket.width &&
                   ball.top > bucket.top && ball.top < bucket.top + bucket.height / 3;
            */

            return ball.left > bucket.left &&
                   ball.left < bucket.left + bucket.width &&
                   ball.top > bucket.top && ball.top < bucket.top + bucket.height / 3;
        },

        adjustScore: function () {
            if (threePointer) lastScore = 3;
            else lastScore = 2;

            // ball type score
            if (ballType == 1) {
                lastScore = 10;
            }

            score += lastScore;
            scoreboard.innerHTML = score;
        },

        execute: function (bucket, context, time) {
            if (ballInFlight && this.ballInBucket()) {
                reset();
                this.adjustScore();
            }
        }
    },

    BUCKET_X = 668,
    BUCKET_Y = canvas.height - 100,
    bucketImage = new Image(),

    bucket = new Sprite('bucket',
      {
          paint: function (sprite, context) {
              context.drawImage(bucketImage, BUCKET_X, BUCKET_Y);
          }
      },

      [catchBall]
    );

    // Functions.....................................................

    function windowToCanvas(x, y) {
        var bbox = canvas.getBoundingClientRect();

        return {
            x: x - bbox.left * (canvas.width / bbox.width),
            y: y - bbox.top * (canvas.height / bbox.height)
        };
    }

    function reset() {
        ball.left = LAUNCHPAD_X + LAUNCHPAD_WIDTH / 2;
        ball.top = LAUNCHPAD_Y - ball.height / 2;
        ball.velocityX = 0;
        ball.velocityY = 0;
        ballInFlight = false;
        needInstructions = false;
        lastScore = 0;
    }

    function showText(text) {
        var metrics;

        context.font = '42px Helvetica';
        metrics = context.measureText(text);

        context.save();
        context.shadowColor = undefined;
        context.strokeStyle = 'rgb(80,120,210)';
        context.fillStyle = 'rgba(100,140,230,0.5)';

        context.fillText(text,
                         canvas.width / 2 - metrics.width / 2,
                         canvas.height / 2);

        context.strokeText(text,
                           canvas.width / 2 - metrics.width / 2,
                           canvas.height / 2);
        context.restore();
    }

    function drawGuidewire() {
        context.moveTo(ball.left, ball.top);
        context.lineTo(lastMouse.left, lastMouse.top);
        context.stroke();
    };

    function updateBackgroundText() {
        if (lastScore == 3) showText('Three pointer!');
        else if (lastScore == 2) showText('Nice shot!');
        else if (lastScore == 10) showText("Wow, you are awesome!");
        else if (needInstructions) showText('Click to launch ball');
    };

    function resetScoreLater() {
        setTimeout(function () {
            lastScore = 0;
        }, 1000);
    };

    function updateSprites(time) {
        bucket.update(context, time);
        launchPad.update(context, time);
        ball.update(context, time);
    }

    function paintSprites() {
        launchPad.paint(context);
        bucket.paint(context);
        ball.paint(context);
    }

    // Event handlers................................................

    canvas.onmousedown = function (e) {
        var rect;

        e.preventDefault();

        if (!ballInFlight) {
            ball.velocityX = launchVelocity * Math.cos(launchAngle);
            ball.velocityY = launchVelocity * Math.sin(launchAngle);
            ballInFlight = true;
            threePointer = false;
            launchTime = undefined;
        }
    };

    canvas.onmousemove = function (e) {
        var rect;

        e.preventDefault();

        if (!ballInFlight) {
            loc = windowToCanvas(e.clientX, e.clientY);
            lastMouse.left = loc.x;
            lastMouse.top = loc.y;

            deltaX = Math.abs(lastMouse.left - ball.left);
            deltaY = Math.abs(lastMouse.top - ball.top);

            launchAngle = Math.atan(parseFloat(deltaY) / parseFloat(deltaX));
            launchVelocity = 4 * deltaY / Math.sin(launchAngle) / pixelsPerMeter;

            launchVelocityOutput.innerHTML = launchVelocity.toFixed(2);
            launchAngleOutput.innerHTML = (launchAngle * 180 / Math.PI).toFixed(2);
        }
    };

    // Animation Loop................................................

    function animate(time) {
        context.clearRect(0, 0, canvas.width, canvas.height);

        if (!ballInFlight) {
            drawGuidewire();
            updateBackgroundText();

            if (lastScore !== 0) { // just scored
                resetScoreLater();
            }
        }

        updateSprites(time);
        paintSprites();

        window.requestNextAnimationFrame(animate);
    }

    // Initialization................................................

    ball.width = BALL_RADIUS * 2;
    ball.height = ball.width;
    ball.left = LAUNCHPAD_X + LAUNCHPAD_WIDTH / 2;
    ball.top = LAUNCHPAD_Y - ball.height / 2;
    ball.radius = BALL_RADIUS;

    context.lineWidth = 0.5;
    context.strokeStyle = 'rgba(0,0,0,0.5)';
    context.shadowColor = 'rgba(0,0,0,0.5)';
    context.shadowOffsetX = 2;
    context.shadowOffsetY = 2;
    context.shadowBlur = 4;
    context.stroke();

    bucketImage.src = '/Images/game/bucket.png';
    bucketImage.onload = function (e) {
        bucket.left = BUCKET_X;
        bucket.top = BUCKET_Y;
        bucket.width = bucketImage.width;
        bucket.height = bucketImage.height;
    };

    window.requestNextAnimationFrame(animate);

    // random change bucket location (easy mode)
    var bucketCount = 0;
    setInterval(function () {
        switch (bucketCount) {
            case 0:
                BUCKET_X = 100;
                BUCKET_Y = canvas.height - 100;
                break;
            case 1:
                BUCKET_Y = canvas.height - 200;
                break;
            case 2:
                BUCKET_Y = canvas.height - 300;
                break;
            default:
                BUCKET_Y = canvas.height - 100;
                break;
        }

        bucket.left = BUCKET_X;
        bucket.top = BUCKET_Y;

        bucketCount = Math.floor(Math.random() * 3);
    }, 5000);

    // random change bucket location (hard mode)
    /*
    var bucketCount = 0;
    setInterval(function () {
        switch (bucketCount) {
            case 0:
                BUCKET_X = 668;
                BUCKET_Y = canvas.height - 100;
                break;
            case 1:
                BUCKET_X = 668 - 200;
                BUCKET_Y = canvas.height - 200;
                break;
            case 2:
                BUCKET_X = 668;
                BUCKET_Y = canvas.height - 300;
                break;
            case 3:
                BUCKET_X = 668 - 200;
                BUCKET_Y = canvas.height - 100;
                break;
            case 4:
                BUCKET_X = 668 - 200;
                BUCKET_Y = canvas.height - 200;
                break;
            case 5:
                BUCKET_X = 668 - 200;
                BUCKET_Y = canvas.height - 300;
                break;
            default:
                BUCKET_X = 668;
                BUCKET_Y = canvas.height - 100;
                break;
        }

        bucketCount = Math.floor(Math.random() * 6);
    }, 5000);
    */

    var ballTypeCount = 0;
    setInterval(function () {
        switch (ballTypeCount) {
            case 0:
                ballType = 0;
                ballPainter.BALL_FILL_STYLE = 'rgb(255,255,0)';
                break;
            case 1:
                ballType = 1;
                ballPainter.BALL_FILL_STYLE = 'rgb(247,0,123)';
                break;
            case 2:
                ballType = 0;
                ballPainter.BALL_FILL_STYLE = 'rgb(255,255,0)';
                break;
            default:
                ballType = 0;
                ballPainter.BALL_FILL_STYLE = 'rgb(255,255,0)';
                break;
        }

        ballTypeCount = Math.floor(Math.random() * 3);
    }, 10000);
</script>

